<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "https://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/xhtml;charset=UTF-8"/>
<meta http-equiv="X-UA-Compatible" content="IE=11"/>
<meta name="generator" content="Doxygen 1.9.4"/>
<meta name="viewport" content="width=device-width, initial-scale=1"/>
<title>Flow: flow::log::Logger Class Reference</title>
<link href="tabs.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="dynsections.js"></script>
<link href="search/search.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="search/searchdata.js"></script>
<script type="text/javascript" src="search/search.js"></script>
<link href="doxygen.css" rel="stylesheet" type="text/css" />
</head>
<body>
<div id="top"><!-- do not remove this div, it is closed by doxygen! -->
<div id="titlearea">
<table cellspacing="0" cellpadding="0">
 <tbody>
 <tr id="projectrow">
  <td id="projectalign">
   <div id="projectname">Flow<span id="projectnumber">&#160;2.0.0</span>
   </div>
   <div id="projectbrief">Flow project: Full implementation reference.</div>
  </td>
 </tr>
 </tbody>
</table>
</div>
<!-- end header part -->
<!-- Generated by Doxygen 1.9.4 -->
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
var searchBox = new SearchBox("searchBox", "search",'Search','.html');
/* @license-end */
</script>
<script type="text/javascript" src="menudata.js"></script>
<script type="text/javascript" src="menu.js"></script>
<script type="text/javascript">
/* @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&amp;dn=expat.txt MIT */
$(function() {
  initMenu('',true,false,'search.php','Search');
  $(document).ready(function() { init_search(); });
});
/* @license-end */
</script>
<div id="main-nav"></div>
<!-- window showing the filter options -->
<div id="MSearchSelectWindow"
     onmouseover="return searchBox.OnSearchSelectShow()"
     onmouseout="return searchBox.OnSearchSelectHide()"
     onkeydown="return searchBox.OnSearchSelectKey(event)">
</div>

<!-- iframe showing the search results (closed by default) -->
<div id="MSearchResultsWindow">
<iframe src="javascript:void(0)" frameborder="0" 
        name="MSearchResults" id="MSearchResults">
</iframe>
</div>

<div id="nav-path" class="navpath">
  <ul>
<li class="navelem"><a class="el" href="namespaceflow.html">flow</a></li><li class="navelem"><a class="el" href="namespaceflow_1_1log.html">log</a></li><li class="navelem"><a class="el" href="classflow_1_1log_1_1Logger.html">Logger</a></li>  </ul>
</div>
</div><!-- top -->
<div class="header">
  <div class="summary">
<a href="#pub-methods">Public Member Functions</a> &#124;
<a href="#pub-static-methods">Static Public Member Functions</a> &#124;
<a href="#pri-static-attribs">Static Private Attributes</a> &#124;
<a href="classflow_1_1log_1_1Logger-members.html">List of all members</a>  </div>
  <div class="headertitle"><div class="title">flow::log::Logger Class Reference<span class="mlabels"><span class="mlabel">abstract</span></span></div></div>
</div><!--header-->
<div class="contents">

<p>Interface that the user should implement, passing the implementing <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> into logging classes (Flow's own classes like <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">net_flow::Node</a>; and user's own logging classes) at construction (plus free/<code>static</code> logging functions).  
 <a href="classflow_1_1log_1_1Logger.html#details">More...</a></p>

<p><code>#include &lt;<a class="el" href="log_8hpp_source.html">log.hpp</a>&gt;</code></p>
<div class="dynheader">
Inheritance diagram for flow::log::Logger:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1log_1_1Logger__inherit__graph.svg" width="538" height="216"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
<center><span class="legend">[<a href="graph_legend.html">legend</a>]</span></center></div>
<div class="dynheader">
Collaboration diagram for flow::log::Logger:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1log_1_1Logger__coll__graph.svg" width="836" height="206"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
<center><span class="legend">[<a href="graph_legend.html">legend</a>]</span></center></div>
<table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pub-methods" name="pub-methods"></a>
Public Member Functions</h2></td></tr>
<tr class="memitem:ac8a2e7a33fe3fbc0c29ead62ed98c022"><td class="memItemLeft" align="right" valign="top">virtual <a class="el" href="classbool.html">bool</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Logger.html#ac8a2e7a33fe3fbc0c29ead62ed98c022">should_log</a> (<a class="el" href="namespaceflow_1_1log.html#a5c602384e6fe9d7642740ac2fae4ad04">Sev</a> sev, const <a class="el" href="classflow_1_1log_1_1Component.html">Component</a> &amp;component) const =0</td></tr>
<tr class="memdesc:ac8a2e7a33fe3fbc0c29ead62ed98c022"><td class="mdescLeft">&#160;</td><td class="mdescRight">Given attributes of a hypothetical message that would be logged, return <code>true</code> if that message should be logged and <code>false</code> otherwise (e.g., if the verbosity of the message is above the current configured verbosity threshold for the <a class="el" href="classflow_1_1log_1_1Component.html" title="A light-weight class, each object storing a component payload encoding an enum value from enum type o...">Component</a> specified).  <a href="classflow_1_1log_1_1Logger.html#ac8a2e7a33fe3fbc0c29ead62ed98c022">More...</a><br /></td></tr>
<tr class="separator:ac8a2e7a33fe3fbc0c29ead62ed98c022"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ae04868e2a384e60a349ecba8340cd731"><td class="memItemLeft" align="right" valign="top">virtual <a class="el" href="classbool.html">bool</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Logger.html#ae04868e2a384e60a349ecba8340cd731">logs_asynchronously</a> () const =0</td></tr>
<tr class="memdesc:ae04868e2a384e60a349ecba8340cd731"><td class="mdescLeft">&#160;</td><td class="mdescRight">Must return <code>true</code> if <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> at least sometimes logs the given message and metadata (e.g., time stamp) after <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> returns; <code>false</code> if this never occurs (i.e., it logs synchronously, always).  <a href="classflow_1_1log_1_1Logger.html#ae04868e2a384e60a349ecba8340cd731">More...</a><br /></td></tr>
<tr class="separator:ae04868e2a384e60a349ecba8340cd731"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a934667f16dd6ca0841e521296ab3a6e2"><td class="memItemLeft" align="right" valign="top">virtual void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2">do_log</a> (<a class="el" href="structflow_1_1log_1_1Msg__metadata.html">Msg_metadata</a> *metadata, <a class="el" href="namespaceflow_1_1util.html#ae4dc52186797094b3040379ff19124c9">util::String_view</a> msg)=0</td></tr>
<tr class="memdesc:a934667f16dd6ca0841e521296ab3a6e2"><td class="mdescLeft">&#160;</td><td class="mdescRight">Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it should be logged (i.e., without performing logic that <a class="el" href="classflow_1_1log_1_1Logger.html#ac8a2e7a33fe3fbc0c29ead62ed98c022" title="Given attributes of a hypothetical message that would be logged, return true if that message should b...">should_log()</a> performs).  <a href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2">More...</a><br /></td></tr>
<tr class="separator:a934667f16dd6ca0841e521296ab3a6e2"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:ad6ead44c19a7b15111b2f77656a2ea31"><td class="memItemLeft" align="right" valign="top">std::ostream *&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Logger.html#ad6ead44c19a7b15111b2f77656a2ea31">this_thread_ostream</a> () const</td></tr>
<tr class="memdesc:ad6ead44c19a7b15111b2f77656a2ea31"><td class="mdescLeft">&#160;</td><td class="mdescRight">Returns the stream dedicated to the executing thread and <code>this</code> <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a>, so that the caller can apply state-setting formatters to it.  <a href="classflow_1_1log_1_1Logger.html#ad6ead44c19a7b15111b2f77656a2ea31">More...</a><br /></td></tr>
<tr class="separator:ad6ead44c19a7b15111b2f77656a2ea31"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="inherit_header pub_methods_classflow_1_1util_1_1Null__interface"><td colspan="2" onclick="javascript:toggleInherit('pub_methods_classflow_1_1util_1_1Null__interface')"><img src="closed.png" alt="-"/>&#160;Public Member Functions inherited from <a class="el" href="classflow_1_1util_1_1Null__interface.html">flow::util::Null_interface</a></td></tr>
<tr class="memitem:a5916282577627e424a09884347eddbba inherit pub_methods_classflow_1_1util_1_1Null__interface"><td class="memItemLeft" align="right" valign="top">virtual&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1util_1_1Null__interface.html#a5916282577627e424a09884347eddbba">~Null_interface</a> ()=0</td></tr>
<tr class="memdesc:a5916282577627e424a09884347eddbba inherit pub_methods_classflow_1_1util_1_1Null__interface"><td class="mdescLeft">&#160;</td><td class="mdescRight">Boring <code>virtual</code> destructor.  <a href="classflow_1_1util_1_1Null__interface.html#a5916282577627e424a09884347eddbba">More...</a><br /></td></tr>
<tr class="separator:a5916282577627e424a09884347eddbba inherit pub_methods_classflow_1_1util_1_1Null__interface"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="inherit_header pub_methods_classflow_1_1util_1_1Unique__id__holder"><td colspan="2" onclick="javascript:toggleInherit('pub_methods_classflow_1_1util_1_1Unique__id__holder')"><img src="closed.png" alt="-"/>&#160;Public Member Functions inherited from <a class="el" href="classflow_1_1util_1_1Unique__id__holder.html">flow::util::Unique_id_holder</a></td></tr>
<tr class="memitem:a90705293787069f52372638d5450ef52 inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="memItemLeft" align="right" valign="top">&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#a90705293787069f52372638d5450ef52">Unique_id_holder</a> ()</td></tr>
<tr class="memdesc:a90705293787069f52372638d5450ef52 inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="mdescLeft">&#160;</td><td class="mdescRight">Thread-safely construct an ID whose value is different from any other object of this class, past or future.  <a href="classflow_1_1util_1_1Unique__id__holder.html#a90705293787069f52372638d5450ef52">More...</a><br /></td></tr>
<tr class="separator:a90705293787069f52372638d5450ef52 inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:abb06f3132d6a6d1d0c509cbd50b9f768 inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="memItemLeft" align="right" valign="top">&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#abb06f3132d6a6d1d0c509cbd50b9f768">Unique_id_holder</a> (const <a class="el" href="classflow_1_1util_1_1Unique__id__holder.html">Unique_id_holder</a> &amp;)</td></tr>
<tr class="memdesc:abb06f3132d6a6d1d0c509cbd50b9f768 inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="mdescLeft">&#160;</td><td class="mdescRight">This copy constructor is identical in behavior to <a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#a90705293787069f52372638d5450ef52" title="Thread-safely construct an ID whose value is different from any other object of this class,...">Unique_id_holder()</a>, the default ctor.  <a href="classflow_1_1util_1_1Unique__id__holder.html#abb06f3132d6a6d1d0c509cbd50b9f768">More...</a><br /></td></tr>
<tr class="separator:abb06f3132d6a6d1d0c509cbd50b9f768 inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a24742b697933e623df30056aebbebfae inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="memItemLeft" align="right" valign="top"><a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#af9cbe2432658aac398498e0a7e96405f">id_t</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#a24742b697933e623df30056aebbebfae">unique_id</a> () const</td></tr>
<tr class="memdesc:a24742b697933e623df30056aebbebfae inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="mdescLeft">&#160;</td><td class="mdescRight">Raw unique ID identifying this object as well as any object of a derived type.  <a href="classflow_1_1util_1_1Unique__id__holder.html#a24742b697933e623df30056aebbebfae">More...</a><br /></td></tr>
<tr class="separator:a24742b697933e623df30056aebbebfae inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:abb6bab931f868d2a2e933d94f7540b1c inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="memItemLeft" align="right" valign="top">const <a class="el" href="classflow_1_1util_1_1Unique__id__holder.html">Unique_id_holder</a> &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#abb6bab931f868d2a2e933d94f7540b1c">operator=</a> (const <a class="el" href="classflow_1_1util_1_1Unique__id__holder.html">Unique_id_holder</a> &amp;) const</td></tr>
<tr class="memdesc:abb6bab931f868d2a2e933d94f7540b1c inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="mdescLeft">&#160;</td><td class="mdescRight">This assignment operator is a <code>const</code> no-op.  <a href="classflow_1_1util_1_1Unique__id__holder.html#abb6bab931f868d2a2e933d94f7540b1c">More...</a><br /></td></tr>
<tr class="separator:abb6bab931f868d2a2e933d94f7540b1c inherit pub_methods_classflow_1_1util_1_1Unique__id__holder"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pub-static-methods" name="pub-static-methods"></a>
Static Public Member Functions</h2></td></tr>
<tr class="memitem:a5600c71ccaa294650c7d34b596d90bf5"><td class="memItemLeft" align="right" valign="top">static void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5">this_thread_set_logged_nickname</a> (<a class="el" href="namespaceflow_1_1util.html#ae4dc52186797094b3040379ff19124c9">util::String_view</a> thread_nickname=<a class="el" href="namespaceflow_1_1util.html#ae4dc52186797094b3040379ff19124c9">util::String_view</a>(), <a class="el" href="classflow_1_1log_1_1Logger.html">Logger</a> *logger_ptr=0, <a class="el" href="classbool.html">bool</a> also_set_os_name=true)</td></tr>
<tr class="memdesc:a5600c71ccaa294650c7d34b596d90bf5"><td class="mdescLeft">&#160;</td><td class="mdescRight">Sets or unsets the current thread's logging-worthy string name; optionally sets the OS thread name (such as visible in <code>top</code> output).  <a href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5">More...</a><br /></td></tr>
<tr class="separator:a5600c71ccaa294650c7d34b596d90bf5"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a93541a6407b8705a76c7a161c5289b10"><td class="memItemLeft" align="right" valign="top">static std::ostream &amp;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Logger.html#a93541a6407b8705a76c7a161c5289b10">this_thread_logged_name_os_manip</a> (std::ostream &amp;os)</td></tr>
<tr class="memdesc:a93541a6407b8705a76c7a161c5289b10"><td class="mdescLeft">&#160;</td><td class="mdescRight"><code>ostream</code> manipulator function that, if output via <code>operator&lt;&lt;</code> to an <code>ostream</code>, will cause the current thread's logging-worthy string name to be output to that stream.  <a href="classflow_1_1log_1_1Logger.html#a93541a6407b8705a76c7a161c5289b10">More...</a><br /></td></tr>
<tr class="separator:a93541a6407b8705a76c7a161c5289b10"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a2d1a0283764e5f85abf00c7cee4c4e19"><td class="memItemLeft" align="right" valign="top">static void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Logger.html#a2d1a0283764e5f85abf00c7cee4c4e19">set_thread_info_in_msg_metadata</a> (<a class="el" href="structflow_1_1log_1_1Msg__metadata.html">Msg_metadata</a> *msg_metadata)</td></tr>
<tr class="memdesc:a2d1a0283764e5f85abf00c7cee4c4e19"><td class="mdescLeft">&#160;</td><td class="mdescRight">Loads <code>msg_metadata-&gt;m_call_thread_nickname</code> (if set) or else <code>msg_metadata-&gt;m_call_thread_id</code>, based on whether/how <a class="el" href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5" title="Sets or unsets the current thread&#39;s logging-worthy string name; optionally sets the OS thread name (s...">this_thread_set_logged_nickname()</a> was last called in the current thread.  <a href="classflow_1_1log_1_1Logger.html#a2d1a0283764e5f85abf00c7cee4c4e19">More...</a><br /></td></tr>
<tr class="separator:a2d1a0283764e5f85abf00c7cee4c4e19"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="memitem:a1ea9da10a13d3b422ba7162a13d7eeb1"><td class="memItemLeft" align="right" valign="top">static void&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Logger.html#a1ea9da10a13d3b422ba7162a13d7eeb1">set_thread_info</a> (std::string *call_thread_nickname, <a class="el" href="namespaceflow_1_1util.html#a0a4e7b2d3107bd630e0dc0c0b8f2e4de">flow::util::Thread_id</a> *call_thread_id)</td></tr>
<tr class="memdesc:a1ea9da10a13d3b422ba7162a13d7eeb1"><td class="mdescLeft">&#160;</td><td class="mdescRight">Same as <a class="el" href="classflow_1_1log_1_1Logger.html#a2d1a0283764e5f85abf00c7cee4c4e19" title="Loads msg_metadata-&gt;m_call_thread_nickname (if set) or else msg_metadata-&gt;m_call_thread_id,...">set_thread_info_in_msg_metadata()</a> but targets the given two variables as opposed to a <a class="el" href="structflow_1_1log_1_1Msg__metadata.html" title="Simple data store containing all of the information generated at every logging call site by flow::log...">Msg_metadata</a>.  <a href="classflow_1_1log_1_1Logger.html#a1ea9da10a13d3b422ba7162a13d7eeb1">More...</a><br /></td></tr>
<tr class="separator:a1ea9da10a13d3b422ba7162a13d7eeb1"><td class="memSeparator" colspan="2">&#160;</td></tr>
<tr class="inherit_header pub_static_methods_classflow_1_1util_1_1Unique__id__holder"><td colspan="2" onclick="javascript:toggleInherit('pub_static_methods_classflow_1_1util_1_1Unique__id__holder')"><img src="closed.png" alt="-"/>&#160;Static Public Member Functions inherited from <a class="el" href="classflow_1_1util_1_1Unique__id__holder.html">flow::util::Unique_id_holder</a></td></tr>
<tr class="memitem:a50489177a7731618ca130468c3872748 inherit pub_static_methods_classflow_1_1util_1_1Unique__id__holder"><td class="memItemLeft" align="right" valign="top">static <a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#af9cbe2432658aac398498e0a7e96405f">id_t</a>&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#a50489177a7731618ca130468c3872748">create_unique_id</a> ()</td></tr>
<tr class="memdesc:a50489177a7731618ca130468c3872748 inherit pub_static_methods_classflow_1_1util_1_1Unique__id__holder"><td class="mdescLeft">&#160;</td><td class="mdescRight">Short-hand for <code><a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#a90705293787069f52372638d5450ef52" title="Thread-safely construct an ID whose value is different from any other object of this class,...">Unique_id_holder()</a>.<a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#a24742b697933e623df30056aebbebfae" title="Raw unique ID identifying this object as well as any object of a derived type.">unique_id()</a></code>; useful when all you want is the unique integer itself.  <a href="classflow_1_1util_1_1Unique__id__holder.html#a50489177a7731618ca130468c3872748">More...</a><br /></td></tr>
<tr class="separator:a50489177a7731618ca130468c3872748 inherit pub_static_methods_classflow_1_1util_1_1Unique__id__holder"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="pri-static-attribs" name="pri-static-attribs"></a>
Static Private Attributes</h2></td></tr>
<tr class="memitem:a3e00a68f9086f1ef0f4e36b9f23f4d02"><td class="memItemLeft" align="right" valign="top">static boost::thread_specific_ptr&lt; std::string &gt;&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1log_1_1Logger.html#a3e00a68f9086f1ef0f4e36b9f23f4d02">s_this_thread_nickname_ptr</a></td></tr>
<tr class="memdesc:a3e00a68f9086f1ef0f4e36b9f23f4d02"><td class="mdescLeft">&#160;</td><td class="mdescRight">Thread-local storage for each thread's logged name (null pointer, which is default, means no nickname stored).  <a href="classflow_1_1log_1_1Logger.html#a3e00a68f9086f1ef0f4e36b9f23f4d02">More...</a><br /></td></tr>
<tr class="separator:a3e00a68f9086f1ef0f4e36b9f23f4d02"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table><table class="memberdecls">
<tr class="heading"><td colspan="2"><h2 class="groupheader"><a id="inherited" name="inherited"></a>
Additional Inherited Members</h2></td></tr>
<tr class="inherit_header pub_types_classflow_1_1util_1_1Unique__id__holder"><td colspan="2" onclick="javascript:toggleInherit('pub_types_classflow_1_1util_1_1Unique__id__holder')"><img src="closed.png" alt="-"/>&#160;Public Types inherited from <a class="el" href="classflow_1_1util_1_1Unique__id__holder.html">flow::util::Unique_id_holder</a></td></tr>
<tr class="memitem:af9cbe2432658aac398498e0a7e96405f inherit pub_types_classflow_1_1util_1_1Unique__id__holder"><td class="memItemLeft" align="right" valign="top">using&#160;</td><td class="memItemRight" valign="bottom"><a class="el" href="classflow_1_1util_1_1Unique__id__holder.html#af9cbe2432658aac398498e0a7e96405f">id_t</a> = uint64_t</td></tr>
<tr class="memdesc:af9cbe2432658aac398498e0a7e96405f inherit pub_types_classflow_1_1util_1_1Unique__id__holder"><td class="mdescLeft">&#160;</td><td class="mdescRight">Raw integer type to uniquely identify a thing. 64-bit width should make overflow extremely hard to reach.  <a href="classflow_1_1util_1_1Unique__id__holder.html#af9cbe2432658aac398498e0a7e96405f">More...</a><br /></td></tr>
<tr class="separator:af9cbe2432658aac398498e0a7e96405f inherit pub_types_classflow_1_1util_1_1Unique__id__holder"><td class="memSeparator" colspan="2">&#160;</td></tr>
</table>
<a name="details" id="details"></a><h2 class="groupheader">Detailed Description</h2>
<div class="textblock"><p >Interface that the user should implement, passing the implementing <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> into logging classes (Flow's own classes like <a class="el" href="classflow_1_1net__flow_1_1Node.html" title="An object of this class is a single Flow-protocol networking node, in the sense that: (1) it has a di...">net_flow::Node</a>; and user's own logging classes) at construction (plus free/<code>static</code> logging functions). </p>
<p >The class (or function) will then implicitly use that <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> in the logging apparatus (such as <code>FLOW_LOG_...()</code> macros) to log messages into the user's preferred logging output(s). One can think of the class implementing this interface as the glue between Flow logging and either the user's lower-level logging system or some output device (like console, files) directly.</p>
<p >The reason <a class="el" href="classflow_1_1log_1_1Logger.html#ac8a2e7a33fe3fbc0c29ead62ed98c022" title="Given attributes of a hypothetical message that would be logged, return true if that message should b...">should_log()</a> and <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> are decoupled like this is for a fast implementation of the <code>FLOW_LOG_...()</code> macros (see <a class="el" href="log_8hpp.html#a692bbadd8b5c3e9cef7a0bbea1915e66" title="Logs a message of the specified severity into flow::log::Logger *get_logger() with flow::log::Compone...">FLOW_LOG_WITH_CHECKING()</a> in particular).</p>
<p >There is also a small set of app-wide (<code>static</code>) utilities, including the ability to nickname any given thread, which causes that nickname (instead of the thread ID) to be logged in subsequent log messages.</p>
<h3>Stream continuity (and threads)</h3>
<p >As slightly advanced <code>ostream</code> users know, an <code>ostream</code> carries state that can be set via explicit method calls such as <code>ostream::setf()</code> and via "printing" manipulators such as <code>std::hex</code> to a given <code>ostream</code>. Regular values printed to <code>ostream</code> will come out differently depending on the current state (e.g., <code>&lt;&lt; 14</code> may show up as a decimal or a hex integer depending on preceding formatters). If you use these state-affecting features, be aware of the following semantics:</p>
<ul>
<li>The system works as if there is exactly one <code>ostream</code> for every distinct combination (<code>logger</code>, T), where:<ul>
<li><code>logger</code> is a distinct <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> object, as identified by the address in its <code>Logger::this</code> pointer.</li>
<li>T is a distinct thread such that the API user has previously, at least once, invoked a logging API that works with <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> <code>ostream</code>s &ndash; from that thread. (The APIs that qualify are essentially various APIs that actually log messages or attempt to set formatting for subsequent messages or are used to subsequently do either.)</li>
</ul>
</li>
<li>One can think of a given (<code>logger</code>, T) combo's <code>ostream</code> as being created on-demand the first time a given <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> <code>logger</code> attempts to do something logging-related from a given thread T. Subsequently, with that combo used again and again, the stream is internally looked up with high performance. The on-demand creation is slower but relatively rare given the low expected count of threads and <code><a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></code>s.</li>
<li>Any stream state change carried by a user API call for a given distinct (as defined above) stream S:<ul>
<li><em>will</em> persistently affect the subsequent output of any subsequent log message payload on stream S, including the same log message following the given state change, and including any subsequent log messages;</li>
<li><em>will not</em> affect any stream other than S;</li>
<li><em>will not</em> affect any intra-message prefixes or suffixes (such as originating file, function, line that may be inserted before every log message automatically) added by the <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> API implementation.</li>
</ul>
</li>
<li>There are essentially two ways to affect state of stream S. Either one must be invoked from the thread T pertaining to stream S, and the <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> object involved must also be the one pertaining to S.<ul>
<li>The state change may be part of the sequence of <code>operator&lt;&lt;()</code> operands passed to a logging API. However, note that for it to take effect, it must not be filtered out by a Sev filter check (basically, the containing log message must actually end up in the log, not filtered away).<ul>
<li>In this case, the state change must be via a manipulator formatter like <code>std::setfill</code>, <code>std::hex</code>, <code>boost::chrono::seconds</code>, etc.</li>
</ul>
</li>
<li>The state change may be a direct call invoked on a given <code>ostream S</code>, where to get access to <code>S</code> one would call <a class="el" href="classflow_1_1log_1_1Logger.html#ad6ead44c19a7b15111b2f77656a2ea31" title="Returns the stream dedicated to the executing thread and this Logger, so that the caller can apply st...">Logger::this_thread_ostream()</a> to receive the pointer &lsquo;&amp;S&rsquo;, for the current thread and the <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> on which the method is executed. Once you have <code>S</code>, you may call state manipulators such as <code>S.setf();</code> or, again, manipulators via <code>S &lt;&lt; std::hex;</code> and similar.<ul>
<li>Using <a class="el" href="classflow_1_1log_1_1Logger.html#ad6ead44c19a7b15111b2f77656a2ea31" title="Returns the stream dedicated to the executing thread and this Logger, so that the caller can apply st...">this_thread_ostream()</a> for any purpose other than to change stream state (i.e., to output actual characters, like <code>S &lt;&lt; "Hello, world!";</code>) will result in undefined behavior. Do not. Use logging APIs for that.</li>
</ul>
</li>
</ul>
</li>
<li>Even if the <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> implementation uses <code>ostream</code> for ultimate output of characters (and it absolutely does not have to do any such thing), that <code>ostream</code> is totally orthogonal and irrelevant to the one being discussed here. E.g., <a class="el" href="classflow_1_1log_1_1Simple__ostream__logger.html" title="An implementation of Logger that logs messages to the given ostreams (e.g., cout or an ofstream for a...">Simple_ostream_logger</a> may print to <code>std::cout</code>, but the formatters we are discussing affect a totally different, internal stream, not that <code>std::cout</code>. In fact, the internal stream is in memory, not file/console/whatever. I point this out only to avoid confusion.</li>
</ul>
<h3>Basic suggested strategy for implementing a <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></h3>
<p >The simplicity of the <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> interface, and the lack of mandatory rigidity in how one might configure it (particularly w/r/t per-<code><a class="el" href="classflow_1_1log_1_1Component.html" title="A light-weight class, each object storing a component payload encoding an enum value from enum type o...">Component</a></code> verbosity and output format), assures the sky is the limit for how one implements their own custom <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a>. However, in the absence of great reasons not to, we suggest one follows the lead of out-of-the-box existing <code><a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></code>s in Flow, which adds a degree of rigidity as to the implementation but also seems to provide all the features seemingly commonly desired in practice. Namely, like (say) <a class="el" href="classflow_1_1log_1_1Simple__ostream__logger.html" title="An implementation of Logger that logs messages to the given ostreams (e.g., cout or an ofstream for a...">Simple_ostream_logger</a>, <a class="el" href="classflow_1_1log_1_1Buffer__logger.html" title="An implementation of Logger that logs messages to an internal std::string buffer and provides read-on...">Buffer_logger</a>, and <a class="el" href="classflow_1_1log_1_1Async__file__logger.html" title="An implementation of Logger that logs messages to a given file-system path but never blocks any loggi...">Async_file_logger</a>, do this:</p><ul>
<li>Take a <a class="el" href="classflow_1_1log_1_1Config.html" title="Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...">Config</a> pointer at constructor and save it (do not copy the <a class="el" href="classflow_1_1log_1_1Config.html" title="Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...">Config</a>). (There are thread safety implications.)</li>
<li>Internally use some kind of <code>ostream</code>-subclass member to a target device, if at all possible. (boost.asio will let you even write to network this way; but at least console output, file output, and memory string output are 100% practical via <code>ostream</code>s. Existing <code><a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></code>s provide examples.)</li>
<li>Internally use an <a class="el" href="classflow_1_1log_1_1Ostream__log__msg__writer.html" title="Utility class, each object of which wraps a given ostream and outputs discrete messages to it adorned...">Ostream_log_msg_writer</a> to write to said <code>ostream</code>, the formatting thereof being configurable in a uniform way via the saved <a class="el" href="classflow_1_1log_1_1Config.html" title="Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...">Config</a>.</li>
<li>Forward <a class="el" href="classflow_1_1log_1_1Logger.html#ac8a2e7a33fe3fbc0c29ead62ed98c022" title="Given attributes of a hypothetical message that would be logged, return true if that message should b...">should_log()</a> logic to the saved <a class="el" href="classflow_1_1log_1_1Config.html" title="Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...">Config</a> (<a class="el" href="classflow_1_1log_1_1Config.html#ae429a329e31a41ba75f94578b0e7f26c" title="A key output of Config, this computes the verbosity-filtering answer to Logger::should_log() based on...">Config::output_whether_should_log()</a>), so that verbosity is flexibly but uniformly set via <a class="el" href="classflow_1_1log_1_1Config.html" title="Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...">Config</a>.</li>
<li>It is up to the user, now, to set up the <a class="el" href="classflow_1_1log_1_1Config.html" title="Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...">Config</a> appropriately when passing it to your <code><a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></code> subclass constructor. The user would simply follow the documentation for <a class="el" href="classflow_1_1log_1_1Config.html" title="Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...">Config</a>, and you need neither re-implement nor re-document configurability of your <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a>.</li>
</ul>
<p >Reminder: <a class="el" href="classflow_1_1log_1_1Config.html" title="Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...">Config</a> and <a class="el" href="classflow_1_1log_1_1Ostream__log__msg__writer.html" title="Utility class, each object of which wraps a given ostream and outputs discrete messages to it adorned...">Ostream_log_msg_writer</a> are optional to use, and one can use one, both, or neither (though the latter itself does expect one of the former; of course you can just load up your own new <a class="el" href="classflow_1_1log_1_1Config.html" title="Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...">Config</a>, in case you don't want to use a user <a class="el" href="classflow_1_1log_1_1Config.html" title="Class used to configure the filtering and logging behavior of Loggers; its use in your custom Loggers...">Config</a> taken via your constructor API). However, unless there's something insufficient about them, various benefits abound in using both. Furthermore, if something is lacking, consider extending that system to the benefit of all/most other <code><a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></code>s as opposed to throwing it away and re-implementing something new for just your new <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a>.</p>
<p >Having decided on that stuff, you also need to decide whether you will write to the output device/whatever synchronously or asynchronously. To wit, the thread safety discussion:</p>
<h3>Thread safety</h3>
<p >The degree of thread safety for either of the 2 main operations is completely up to the subclass implementer. Informally, we suggest here that you think about this topic carefully. In particular, without locking, <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> may run concurrently with itself from multiple threads; depending on the medium to which it is writing, this may result in corruption or ugly output or turn out fine, depending on how you define "fine." Whether this is a concern or not is up to you. Note, however, that in practice as of this writing <em>at least</em> one Flow module (<a class="el" href="namespaceflow_1_1net__flow.html" title="Flow module containing the API and implementation of the Flow network protocol, a TCP-inspired stream...">flow::net_flow</a>) will definitely potentially execute <a class="el" href="classflow_1_1log_1_1Logger.html#ac8a2e7a33fe3fbc0c29ead62ed98c022" title="Given attributes of a hypothetical message that would be logged, return true if that message should b...">should_log()</a> and <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> concurrently with themselves from multiple threads on the same <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a>. In general that should be expected in all but the simplest single-threaded apps.</p>
<p >Implementation suggestions for <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> subclasses with respect to thread safety: There are 2 likeliest patterns one can use.</p><ol type="1">
<li>One can use a mutex lock around actual writing to the target device. There's nothing inherently un-performant about this, in an of itself, and the implementation is incredibly simple. For example see <a class="el" href="classflow_1_1log_1_1Simple__ostream__logger.html" title="An implementation of Logger that logs messages to the given ostreams (e.g., cout or an ofstream for a...">Simple_ostream_logger</a>. However, there <em>is</em> a significant performance danger if the device-writing itself can be both synchronous and slow. In particular, a file write (when flushing any buffer such as the internal one in <code>FILE*</code> or <code>ofstream</code>), which is likely after each message, is usually synchronous and can be sporadically slow (consider having to spin up a sleeping hard drive for instance). That would not only block the log-call-site thread but also any competing logging threads at that time. That is probably fine in many non-production scenarios, but in a production heavy-duty server it's not OK.<ul>
<li>An informal suggestion: It is fine for console output, probably (standard out, standard err). Otherwise, particularly with files and synchronous networking, don't. Use the following instead:</li>
</ul>
</li>
<li>One can avoid any such lock; instead the log-call-site thread can save the stuff to log (including the message and <a class="el" href="structflow_1_1log_1_1Msg__metadata.html" title="Simple data store containing all of the information generated at every logging call site by flow::log...">Msg_metadata</a> passed to <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a>) and pass it to a dedicated thread (or pool thereof, etc.) in charge of asynchronously queueing up stuff to write to device and actually writing it in the order received at some later time (though typically fairly soon and definitely ASAP in most cases). This is a bit more complex, but with <a class="el" href="namespaceflow_1_1async.html" title="Flow module containing tools enabling multi-threaded event loops operating under the asynchronous-tas...">flow::async</a> it's really pretty easy still. See the heavy-duty <a class="el" href="classflow_1_1log_1_1Async__file__logger.html" title="An implementation of Logger that logs messages to a given file-system path but never blocks any loggi...">Async_file_logger</a> for example.</li>
</ol>
<p >Both general patterns are formally supported. To use pattern 1, have your <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> implementation's <a class="el" href="classflow_1_1log_1_1Logger.html#ae04868e2a384e60a349ecba8340cd731" title="Must return true if do_log() at least sometimes logs the given message and metadata (e....">logs_asynchronously()</a> return <code>false</code>. To use pattern 2, have it use <code>true</code>. The precise implications are documented in doc header of <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a>.</p>
<h3>Order of output requirements</h3>
<p >We assume for this discussion that the notion of order of final output (to device/file/network/whatever) exists, and that the <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> implementation indeed safely outputs message M1 entirely before M2, or vice versa, for every pair of messages (in this context by message we mean message+metadata pair) ever passed to <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a>. With that assumption in effect (IF indeed it is), the present text <em>requires</em> that the following is guaranteed:</p><ul>
<li>In a given thread T, for a given <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> L, if <code>L.do_log(M1);</code> is called before <code>L.do_log(M2)</code>, and both are successfully output by L, then the final output order must have M1 precede M2, not vice versa.</li>
<li>If, instead, M1 is logged in thread T1, while M2 is logged in thread T2:<ul>
<li>If the 2 <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> calls are chronologically disjoint, then again the final output must also have M1 precede M2 if M1 went first; and vice versa.</li>
<li>If the 2 <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> calls chronologically overlap, then either final output order is acceptable. (Ideally, it <em>should</em> reflect the order of entry to <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> in the 2 threads, but it's formally optional. Informally this typically will happen anyway under most basic algorithms imaginable.)</li>
</ul>
</li>
</ul>
<p >Note that this is only tangentially related to any time stamps one might see in the final output.</p>
<p >See also notes on log output order in <a class="el" href="log_8hpp.html#a626c7dc4d3b4dc0b32a8aac8624d66bc" title="Logs a WARNING message into flow::log::Logger *get_logger() with flow::log::Component get_log_compone...">FLOW_LOG_WARNING()</a> doc header (which applies to all log call sites). The behavior described there is a function of the underlying <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> following the above formal requirements for thread-safe <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> implementations. </p>

<p class="definition">Definition at line <a class="el" href="log_8hpp_source.html#l01280">1280</a> of file <a class="el" href="log_8hpp_source.html">log.hpp</a>.</p>
</div><h2 class="groupheader">Member Function Documentation</h2>
<a id="a934667f16dd6ca0841e521296ab3a6e2" name="a934667f16dd6ca0841e521296ab3a6e2"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a934667f16dd6ca0841e521296ab3a6e2">&#9670;&nbsp;</a></span>do_log()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual void flow::log::Logger::do_log </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="structflow_1_1log_1_1Msg__metadata.html">Msg_metadata</a> *&#160;</td>
          <td class="paramname"><em>metadata</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1util.html#ae4dc52186797094b3040379ff19124c9">util::String_view</a>&#160;</td>
          <td class="paramname"><em>msg</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it should be logged (i.e., without performing logic that <a class="el" href="classflow_1_1log_1_1Logger.html#ac8a2e7a33fe3fbc0c29ead62ed98c022" title="Given attributes of a hypothetical message that would be logged, return true if that message should b...">should_log()</a> performs). </p>
<p >The logging is guaranteed to be synchronous if <code>!logs_asynchronously()</code>; but may be asynchronous otherwise (more on this below).</p>
<p >The convenience macros <code>FLOW_LOG_...()</code> combine this with <a class="el" href="classflow_1_1log_1_1Logger.html#ac8a2e7a33fe3fbc0c29ead62ed98c022" title="Given attributes of a hypothetical message that would be logged, return true if that message should b...">should_log()</a> to make it so that a message is only constructed if <code><a class="el" href="classflow_1_1log_1_1Logger.html#ac8a2e7a33fe3fbc0c29ead62ed98c022" title="Given attributes of a hypothetical message that would be logged, return true if that message should b...">should_log()</a> == true</code>, and if so, constructs and logs it; otherwise almost no computing or storage resources are spent, and the message is not logged.</p>
<p >Expectations of what should or should not be included in <code>msg</code> are of some importance. They are as follows. To summarize, <code>msg</code> should include the message (as specified typically as the <code>ARG_stream_fragment</code> arg to <a class="el" href="log_8hpp.html#a626c7dc4d3b4dc0b32a8aac8624d66bc" title="Logs a WARNING message into flow::log::Logger *get_logger() with flow::log::Component get_log_compone...">FLOW_LOG_WARNING()</a> and buddies); and <code>*msg_metadata</code> should include everything else. This design provides maximum flexibility to the <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">Logger::do_log()</a> implementation to structure the final output's contents (in the log file, or console, or wherever) as it sees fit, cosmetically and size-wise.</p>
<p >Note on trailing newline(s): <code>msg</code> must include any trailing newline(s) that are <em>required</em> to be output. By convention, <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> itself will print a message terminator (often in fact a newline) after each message, if applicable. Hence typically there is no trailing newline at the end of most <code>msg</code>s, and one would include N of them if and only if one intentionally desires N trailing blank lines (possible but atypical).</p>
<h3>Precise meaning of <a class="el" href="classflow_1_1log_1_1Logger.html#ae04868e2a384e60a349ecba8340cd731" title="Must return true if do_log() at least sometimes logs the given message and metadata (e....">logs_asynchronously()</a></h3>
<p >Let ASYNC = the value <a class="el" href="classflow_1_1log_1_1Logger.html#ae04868e2a384e60a349ecba8340cd731" title="Must return true if do_log() at least sometimes logs the given message and metadata (e....">logs_asynchronously()</a> returns (note for a given <code>*this</code> it must always be the same value by that API's contract). Then <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> must act as follows:</p><ul>
<li>If ASYNC is <code>false</code>: Do not make a copy of <code>msg</code>; output it synchronously. Do not make a copy of <code>*metadata</code>. Do not <code>delete metadata</code>. Output any of its contents synchronously.</li>
<li>If ASYNC is <code>true</code>: Optionally make a copy of <code>msg</code>, unless you are able to output it synchronously, in which case there is no need. Do not make a copy of <code>*metadata</code>. You <em>must</em> <code>delete metadata</code> at some point; failing to do so <em>will</em> leak it. (Note: We are intentionally avoiding using <code>shared_ptr</code> or even <code>unique_ptr</code>, for the perf savings, since logging is ubiquitous.) Output <code>*metadata</code> contents either synchronously or asynchronously.</li>
</ul>
<p >The only formal requirement, however, is simply: You must <code>delete metadata;</code> at some future point &lt;=iff=&gt; ASYNC is <code>true</code>. The other requirements just above are informal but of no less import.</p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="structflow_1_1log_1_1Msg__metadata.html" title="Simple data store containing all of the information generated at every logging call site by flow::log...">Msg_metadata</a> which includes stuff not to include in <code>msg</code>.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">metadata</td><td>All information to potentially log in addition to <code>msg</code>. </td></tr>
    <tr><td class="paramname">msg</td><td>The message. See details above. Short version: exclude anything from <code>metadata</code>; exclude any ever-present terminating newline. </td></tr>
  </table>
  </dd>
</dl>

<p>Implemented in <a class="el" href="classflow_1_1log_1_1Async__file__logger.html#aa557c0f55c1044161acc8fb54c115a3e">flow::log::Async_file_logger</a>, <a class="el" href="classflow_1_1log_1_1Buffer__logger.html#a2e95b58eabbd6632f2856097a74921ec">flow::log::Buffer_logger</a>, <a class="el" href="classflow_1_1log_1_1Serial__file__logger.html#a2604031c07cbb4753bd3563d519a0872">flow::log::Serial_file_logger</a>, and <a class="el" href="classflow_1_1log_1_1Simple__ostream__logger.html#a44192b92a16bc07f8d99beb6ad25c826">flow::log::Simple_ostream_logger</a>.</p>

</div>
</div>
<a id="ae04868e2a384e60a349ecba8340cd731" name="ae04868e2a384e60a349ecba8340cd731"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ae04868e2a384e60a349ecba8340cd731">&#9670;&nbsp;</a></span>logs_asynchronously()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual <a class="el" href="classbool.html">bool</a> flow::log::Logger::logs_asynchronously </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td> const</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Must return <code>true</code> if <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> at least sometimes logs the given message and metadata (e.g., time stamp) after <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> returns; <code>false</code> if this never occurs (i.e., it logs synchronously, always). </p>
<p ><a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> doc header formally describes the implications of this.</p>
<p >This must always return the same value, for a given <code>*this</code>.</p>
<p >This method is intended for internal use by the <a class="el" href="namespaceflow_1_1log.html" title="Flow module providing logging functionality.">flow::log</a> system; informally it is not expected the user will call it. Technically there is no harm in doing so. (It would have been <code>private</code> but cannot due to certain C++ limitations, and certain contrived ways to do it are just not worth the trouble.)</p>
<p >The "certain C++ limitations" are that <a class="el" href="log_8hpp.html#a5daa2b6d16edea74bb8bddc75f7fb801" title="Identical to FLOW_LOG_WITH_CHECKING() but foregoes the filter (Logger::should_log()) check.">FLOW_LOG_WITHOUT_CHECKING()</a> must access it, but it is a macro and cannot be involved in <code>friend</code>ship. A contrived way to resolve it would be to make some <code>detail/</code> helper free function the <code>friend</code>, which would call this method, and invoke that free function from the macro. All that just to move a harmless thing into <code>private</code> &ndash; I think not worth it, but an argument could be made. </p>
<dl class="section see"><dt>See also</dt><dd><a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a>. </dd></dl>
<dl class="section return"><dt>Returns</dt><dd>See above. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1log_1_1Async__file__logger.html#afd773546633aec017f2041feb3a75dd3">flow::log::Async_file_logger</a>, <a class="el" href="classflow_1_1log_1_1Buffer__logger.html#ac5d382dae85e7c9f0f51e5e6eebd99a5">flow::log::Buffer_logger</a>, <a class="el" href="classflow_1_1log_1_1Serial__file__logger.html#a591d96ecc030af0b40c42a33e2a616d9">flow::log::Serial_file_logger</a>, and <a class="el" href="classflow_1_1log_1_1Simple__ostream__logger.html#a1548d51e8314a9cff0669f20cae9ae76">flow::log::Simple_ostream_logger</a>.</p>

</div>
</div>
<a id="a1ea9da10a13d3b422ba7162a13d7eeb1" name="a1ea9da10a13d3b422ba7162a13d7eeb1"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a1ea9da10a13d3b422ba7162a13d7eeb1">&#9670;&nbsp;</a></span>set_thread_info()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">void flow::log::Logger::set_thread_info </td>
          <td>(</td>
          <td class="paramtype">std::string *&#160;</td>
          <td class="paramname"><em>call_thread_nickname</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1util.html#a0a4e7b2d3107bd630e0dc0c0b8f2e4de">flow::util::Thread_id</a> *&#160;</td>
          <td class="paramname"><em>call_thread_id</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">static</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Same as <a class="el" href="classflow_1_1log_1_1Logger.html#a2d1a0283764e5f85abf00c7cee4c4e19" title="Loads msg_metadata-&gt;m_call_thread_nickname (if set) or else msg_metadata-&gt;m_call_thread_id,...">set_thread_info_in_msg_metadata()</a> but targets the given two variables as opposed to a <a class="el" href="structflow_1_1log_1_1Msg__metadata.html" title="Simple data store containing all of the information generated at every logging call site by flow::log...">Msg_metadata</a>. </p>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000050">Todo:</a></b></dt><dd>It would be more consistent to rename <a class="el" href="classflow_1_1log_1_1Logger.html#a1ea9da10a13d3b422ba7162a13d7eeb1" title="Same as set_thread_info_in_msg_metadata() but targets the given two variables as opposed to a Msg_met...">set_thread_info()</a> to this_thread_set_info(), since it operates in thread-local fashion. This was a naming convention oversight.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">call_thread_nickname</td><td>Non-null pointer to value to modify. See above. </td></tr>
    <tr><td class="paramname">call_thread_id</td><td>Non-null pointer to value to modify. See above. </td></tr>
  </table>
  </dd>
</dl>

<p class="definition">Definition at line <a class="el" href="log_8cpp_source.html#l00125">125</a> of file <a class="el" href="log_8cpp_source.html">log.cpp</a>.</p>

<p class="reference">References <a class="el" href="log_8hpp_source.html#l01552">s_this_thread_nickname_ptr</a>.</p>

<p class="reference">Referenced by <a class="el" href="log_8cpp_source.html#l00144">set_thread_info_in_msg_metadata()</a>.</p>
<div class="dynheader">
Here is the caller graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1log_1_1Logger_a1ea9da10a13d3b422ba7162a13d7eeb1_icgraph.svg" width="331" height="59"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<a id="a2d1a0283764e5f85abf00c7cee4c4e19" name="a2d1a0283764e5f85abf00c7cee4c4e19"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a2d1a0283764e5f85abf00c7cee4c4e19">&#9670;&nbsp;</a></span>set_thread_info_in_msg_metadata()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">void flow::log::Logger::set_thread_info_in_msg_metadata </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="structflow_1_1log_1_1Msg__metadata.html">Msg_metadata</a> *&#160;</td>
          <td class="paramname"><em>msg_metadata</em></td><td>)</td>
          <td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">static</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Loads <code>msg_metadata-&gt;m_call_thread_nickname</code> (if set) or else <code>msg_metadata-&gt;m_call_thread_id</code>, based on whether/how <a class="el" href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5" title="Sets or unsets the current thread&#39;s logging-worthy string name; optionally sets the OS thread name (s...">this_thread_set_logged_nickname()</a> was last called in the current thread. </p>
<p >The two members should be set to ther default-constructed values on entry to the present function.</p>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000049">Todo:</a></b></dt><dd>It would be more consistent to rename <a class="el" href="classflow_1_1log_1_1Logger.html#a2d1a0283764e5f85abf00c7cee4c4e19" title="Loads msg_metadata-&gt;m_call_thread_nickname (if set) or else msg_metadata-&gt;m_call_thread_id,...">set_thread_info_in_msg_metadata()</a> to this_thread_set_info_in_msg_metadata(), since it operates in thread-local fashion. This was a naming convention oversight.</dd></dl>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">msg_metadata</td><td>Non-null pointer to structure to modify. See above. </td></tr>
  </table>
  </dd>
</dl>

<p class="definition">Definition at line <a class="el" href="log_8cpp_source.html#l00144">144</a> of file <a class="el" href="log_8cpp_source.html">log.cpp</a>.</p>

<p class="reference">References <a class="el" href="log_8hpp_source.html#l01137">flow::log::Msg_metadata::m_call_thread_id</a>, <a class="el" href="log_8hpp_source.html#l01127">flow::log::Msg_metadata::m_call_thread_nickname</a>, and <a class="el" href="log_8cpp_source.html#l00125">set_thread_info()</a>.</p>
<div class="dynheader">
Here is the call graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1log_1_1Logger_a2d1a0283764e5f85abf00c7cee4c4e19_cgraph.svg" width="331" height="59"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<a id="ac8a2e7a33fe3fbc0c29ead62ed98c022" name="ac8a2e7a33fe3fbc0c29ead62ed98c022"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ac8a2e7a33fe3fbc0c29ead62ed98c022">&#9670;&nbsp;</a></span>should_log()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">virtual <a class="el" href="classbool.html">bool</a> flow::log::Logger::should_log </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1log.html#a5c602384e6fe9d7642740ac2fae4ad04">Sev</a>&#160;</td>
          <td class="paramname"><em>sev</em>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype">const <a class="el" href="classflow_1_1log_1_1Component.html">Component</a> &amp;&#160;</td>
          <td class="paramname"><em>component</em>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td> const</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">pure virtual</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Given attributes of a hypothetical message that would be logged, return <code>true</code> if that message should be logged and <code>false</code> otherwise (e.g., if the verbosity of the message is above the current configured verbosity threshold for the <a class="el" href="classflow_1_1log_1_1Component.html" title="A light-weight class, each object storing a component payload encoding an enum value from enum type o...">Component</a> specified). </p>
<p >The convenience macros <code>FLOW_LOG_...()</code> combine this with <a class="el" href="classflow_1_1log_1_1Logger.html#a934667f16dd6ca0841e521296ab3a6e2" title="Given a message and its severity, logs that message and possibly severity WITHOUT checking whether it...">do_log()</a> to make it so that a message is only built if <code><a class="el" href="classflow_1_1log_1_1Logger.html#ac8a2e7a33fe3fbc0c29ead62ed98c022" title="Given attributes of a hypothetical message that would be logged, return true if that message should b...">should_log()</a> == true</code>, and (if so) builds and logs it; otherwise almost no computing or storage resources are spent, and the message is neither built nor logged logged. The verb "to build message" here more formally means "to execute the `ostream&lt;&lt;` fragment passed to macro by
writing characters to some internally maintained `ostream` accordingly."</p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">sev</td><td>Severity of the message. </td></tr>
    <tr><td class="paramname">component</td><td><a class="el" href="classflow_1_1log_1_1Component.html" title="A light-weight class, each object storing a component payload encoding an enum value from enum type o...">Component</a> of the message. Reminder: <code>component.empty() == true</code> is allowed; which isn't to say it will or won't result in this method returning <code>true</code>, but that it will return and not act in undefined fashion. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>true</code> if it should be logged; <code>false</code> if it should not. </dd></dl>

<p>Implemented in <a class="el" href="classflow_1_1log_1_1Async__file__logger.html#ad139ac22e5953e52e03648860a15e3fd">flow::log::Async_file_logger</a>, <a class="el" href="classflow_1_1log_1_1Buffer__logger.html#aa27a237d1cc9d3d9f28c472f521f0163">flow::log::Buffer_logger</a>, <a class="el" href="classflow_1_1log_1_1Serial__file__logger.html#ad602948de59867b3a85c7f0dd6620497">flow::log::Serial_file_logger</a>, and <a class="el" href="classflow_1_1log_1_1Simple__ostream__logger.html#aaf1987dc4e163db1c13e6f4407135fa9">flow::log::Simple_ostream_logger</a>.</p>

<p class="reference">Referenced by <a class="el" href="async_2util_8hpp_source.html#l00031">flow::async::asio_exec_ctx_post()</a>, <a class="el" href="checkpt__timer_8cpp_source.html#l00029">flow::perf::Checkpointing_timer::Checkpointing_timer()</a>, <a class="el" href="low__lvl__packet_8cpp_source.html#l00380">flow::net_flow::Low_lvl_packet::create_from_raw_data_packet()</a>, <a class="el" href="basic__blob_8hpp_source.html#l02159">flow::util::Basic_blob&lt; Allocator, S_SHARING_ALLOWED &gt;::emplace_copy()</a>, <a class="el" href="basic__blob_8hpp_source.html#l02111">flow::util::Basic_blob&lt; Allocator, S_SHARING_ALLOWED &gt;::make_zero()</a>, <a class="el" href="basic__blob_8hpp_source.html#l01872">flow::util::Basic_blob&lt; Allocator, S_SHARING_ALLOWED &gt;::reserve()</a>, <a class="el" href="basic__blob_8hpp_source.html#l01673">flow::util::Basic_blob&lt; Allocator, S_SHARING_ALLOWED &gt;::share()</a>, <a class="el" href="basic__blob_8hpp_source.html#l01752">flow::util::Basic_blob&lt; Allocator, S_SHARING_ALLOWED &gt;::share_after_split_equally_impl()</a>, <a class="el" href="basic__blob_8hpp_source.html#l01702">flow::util::Basic_blob&lt; Allocator, S_SHARING_ALLOWED &gt;::share_after_split_left()</a>, <a class="el" href="basic__blob_8hpp_source.html#l01726">flow::util::Basic_blob&lt; Allocator, S_SHARING_ALLOWED &gt;::share_after_split_right()</a>, <a class="el" href="drop__timer_8cpp_source.html#l00347">flow::net_flow::Drop_timer::start_timer()</a>, <a class="el" href="basic__blob_8hpp_source.html#l02221">flow::util::Basic_blob&lt; Allocator, S_SHARING_ALLOWED &gt;::sub_copy()</a>, and <a class="el" href="basic__blob_8hpp_source.html#l01605">flow::util::Basic_blob&lt; Allocator, S_SHARING_ALLOWED &gt;::swap_impl()</a>.</p>
<div class="dynheader">
Here is the caller graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1log_1_1Logger_ac8a2e7a33fe3fbc0c29ead62ed98c022_icgraph.svg" width="1059" height="1159"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<a id="a93541a6407b8705a76c7a161c5289b10" name="a93541a6407b8705a76c7a161c5289b10"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a93541a6407b8705a76c7a161c5289b10">&#9670;&nbsp;</a></span>this_thread_logged_name_os_manip()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">std::ostream &amp; flow::log::Logger::this_thread_logged_name_os_manip </td>
          <td>(</td>
          <td class="paramtype">std::ostream &amp;&#160;</td>
          <td class="paramname"><em>os</em></td><td>)</td>
          <td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">static</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p><code>ostream</code> manipulator function that, if output via <code>operator&lt;&lt;</code> to an <code>ostream</code>, will cause the current thread's logging-worthy string name to be output to that stream. </p>
<p >See <a class="el" href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5" title="Sets or unsets the current thread&#39;s logging-worthy string name; optionally sets the OS thread name (s...">this_thread_set_logged_nickname()</a> for details of what this string will actually be.</p>
<p >Recall that an <code>ostream</code> manipulator is invoked in the style of <code>endl</code> and <code>flush</code>; for example: <code>cout &lt;&lt; endl;</code>. It is atypical to call it directly as opposed to via the overloaded "shift" operator.</p>
<p >Note that typically this is not invoked directly by the user but rather used in the <code>FLOW_LOG_...()</code> macros' implementation guts which is the original use case and hence reason for its existence. However, there's no rule against direct uses, and it could prove useful at some point. Any use beyond logging or debugging is not recommended however (in particular, do not use to make any algorithmic decisions).</p>
<p >This call is safe w/r/t concurrent execution with itself and <a class="el" href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5" title="Sets or unsets the current thread&#39;s logging-worthy string name; optionally sets the OS thread name (s...">this_thread_set_logged_nickname()</a> in other thread(s).</p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">os</td><td>Stream to which to write thread's name. </td></tr>
  </table>
  </dd>
</dl>
<dl class="section return"><dt>Returns</dt><dd><code>os</code>. </dd></dl>

<p class="definition">Definition at line <a class="el" href="log_8cpp_source.html#l00108">108</a> of file <a class="el" href="log_8cpp_source.html">log.cpp</a>.</p>

<p class="reference">References <a class="el" href="log_8hpp_source.html#l01552">s_this_thread_nickname_ptr</a>.</p>

</div>
</div>
<a id="ad6ead44c19a7b15111b2f77656a2ea31" name="ad6ead44c19a7b15111b2f77656a2ea31"></a>
<h2 class="memtitle"><span class="permalink"><a href="#ad6ead44c19a7b15111b2f77656a2ea31">&#9670;&nbsp;</a></span>this_thread_ostream()</h2>

<div class="memitem">
<div class="memproto">
      <table class="memname">
        <tr>
          <td class="memname">std::ostream * flow::log::Logger::this_thread_ostream </td>
          <td>(</td>
          <td class="paramname"></td><td>)</td>
          <td> const</td>
        </tr>
      </table>
</div><div class="memdoc">

<p>Returns the stream dedicated to the executing thread and <code>this</code> <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a>, so that the caller can apply state-setting formatters to it. </p>
<p >If you write characters to it, or otherwise do anything othen than set formatting state, or try to affect buffering behavior, behavior is undefined. Usage example:</p>
<div class="fragment"><div class="line">get_logger()-&gt;this_thread_ostream()-&gt;setf(std::fixed | std::right);</div>
<div class="line">*(get_logger()-&gt;this_thread_ostream()) &lt;&lt; std::setw(2);</div>
<div class="line"><span class="comment">// *get_logger()&#39;s subsequent messages (such as the following) from the current thread will use above formatting.</span></div>
<div class="line"><a class="code hl_define" href="log_8hpp.html#a626c7dc4d3b4dc0b32a8aac8624d66bc">FLOW_LOG_WARNING</a>(<span class="stringliteral">&quot;Let&#39;s print a number with some formatting: &quot;</span> &lt;&lt; 0.5);</div>
<div class="ttc" id="alog_8hpp_html_a626c7dc4d3b4dc0b32a8aac8624d66bc"><div class="ttname"><a href="log_8hpp.html#a626c7dc4d3b4dc0b32a8aac8624d66bc">FLOW_LOG_WARNING</a></div><div class="ttdeci">#define FLOW_LOG_WARNING(ARG_stream_fragment)</div><div class="ttdoc">Logs a WARNING message into flow::log::Logger *get_logger() with flow::log::Component get_log_compone...</div><div class="ttdef"><b>Definition:</b> <a href="log_8hpp_source.html#l00152">log.hpp:152</a></div></div>
</div><!-- fragment --><p >Note that you could just as well apply the intended formatters via regular log statements. However, there are disadvantages to that approach &ndash; but they do not always apply. The disadvantages are listed below; but the short version is you should typically use the present method if and only if you are attempting to affect subsequent logging at large, not a particular fragment of a particular message.</p>
<p >Formally, the disadvantages of affecting formatting state of the underlying stream via log macros:</p><ul>
<li>If the log statement is ignored due to failing a filter check, then any formatters therein will also be ignored. (However, you could use a macro that bypasses such a check. On the other hand, stylistically one would typically only do that after checking the severity manually for performance of combining several log statements with equal severities. Using it <em>just</em> to apply formatters is stylistically dubious.)</li>
<li>If you are trying to affect subsequent logging at large, you'd hypothetically use something like <code>FLOW_LOG_INFO_WITHOUT_CHECKING(...formatter... &lt;&lt; ...formatter... &lt;&lt; ...);</code>. This is stylistically dubious, because the lack of characters being output means the severity (INFO in this case) is disregarded and is a dummy value.</li>
<li>While one can pass many formatters as <code>&lt;&lt;</code> operator arguments, there are others than do not use that syntax. For example, <code>ostream::setf()</code> is a method <em>of</em> <code>std::ostream</code>. Thus the log macros do not help.</li>
</ul>
<p >Recall that the stream involved is completely orthogonal to any underlying stream that may be ultimately output to by <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> for the actual, ultimate output of characters. E.g., if <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> happens to be <a class="el" href="classflow_1_1log_1_1Simple__ostream__logger.html" title="An implementation of Logger that logs messages to the given ostreams (e.g., cout or an ofstream for a...">Simple_ostream_logger</a> targeted at <code>std::cout</code>, the above snippet would in no way touch <code>std::cout</code> formatting. In fact, <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a> may not even use streams for output; that is an orthogonal implementation detail.</p>
<dl class="section return"><dt>Returns</dt><dd>Pointer to stream; always the same value for a given thread and different among all distinct threads. </dd></dl>

<p class="definition">Definition at line <a class="el" href="log_8cpp_source.html#l00150">150</a> of file <a class="el" href="log_8cpp_source.html">log.cpp</a>.</p>

<p class="reference">References <a class="el" href="thread__lcl__str__appender_8cpp_source.html#l00107">flow::log::Thread_local_string_appender::appender_ostream()</a>, and <a class="el" href="thread__lcl__str__appender_8cpp_source.html#l00033">flow::log::Thread_local_string_appender::get_this_thread_string_appender()</a>.</p>

<p class="reference">Referenced by <a class="el" href="log_8cpp_source.html#l00271">flow::log::beautify_chrono_logger_this_thread()</a>.</p>
<div class="dynheader">
Here is the call graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1log_1_1Logger_ad6ead44c19a7b15111b2f77656a2ea31_cgraph.svg" width="562" height="131"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>
<div class="dynheader">
Here is the caller graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1log_1_1Logger_ad6ead44c19a7b15111b2f77656a2ea31_icgraph.svg" width="743" height="107"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<a id="a5600c71ccaa294650c7d34b596d90bf5" name="a5600c71ccaa294650c7d34b596d90bf5"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a5600c71ccaa294650c7d34b596d90bf5">&#9670;&nbsp;</a></span>this_thread_set_logged_nickname()</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">void flow::log::Logger::this_thread_set_logged_nickname </td>
          <td>(</td>
          <td class="paramtype"><a class="el" href="namespaceflow_1_1util.html#ae4dc52186797094b3040379ff19124c9">util::String_view</a>&#160;</td>
          <td class="paramname"><em>thread_nickname</em> = <code><a class="el" href="namespaceflow_1_1util.html#ae4dc52186797094b3040379ff19124c9">util::String_view</a>()</code>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="classflow_1_1log_1_1Logger.html">Logger</a> *&#160;</td>
          <td class="paramname"><em>logger_ptr</em> = <code>0</code>, </td>
        </tr>
        <tr>
          <td class="paramkey"></td>
          <td></td>
          <td class="paramtype"><a class="el" href="classbool.html">bool</a>&#160;</td>
          <td class="paramname"><em>also_set_os_name</em> = <code>true</code>&#160;</td>
        </tr>
        <tr>
          <td></td>
          <td>)</td>
          <td></td><td></td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">static</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Sets or unsets the current thread's logging-worthy string name; optionally sets the OS thread name (such as visible in <code>top</code> output). </p>
<p >The logging-worthy name is always set or unset; the OS name is modified only if <code>also_set_os_name == true</code> arg is set. <code>thread_nickname</code> can thus be set to something more descriptive than any default, such as: "native_main" or "worker_port_2231."</p>
<ul>
<li>The logging-worthy thread string name is accessed as follows:<ul>
<li><code>FLOW_LOG_*()</code> macros pass it automatically to the appropriate <a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">log::Logger</a>. All out-of-the-box <code><a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></code>s will then log either the name set here (if not blank) or the thread ID (if blank). (Custom <code><a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></code>s can ignore these data and not log them; but presumably most will at least optionally log them.)</li>
<li>It can also be obtained directly via <a class="el" href="classflow_1_1log_1_1Logger.html#a93541a6407b8705a76c7a161c5289b10" title="ostream manipulator function that, if output via operator&lt;&lt; to an ostream, will cause the current thr...">this_thread_logged_name_os_manip()</a>, <a class="el" href="classflow_1_1log_1_1Logger.html#a1ea9da10a13d3b422ba7162a13d7eeb1" title="Same as set_thread_info_in_msg_metadata() but targets the given two variables as opposed to a Msg_met...">set_thread_info()</a>, or <a class="el" href="classflow_1_1log_1_1Logger.html#a2d1a0283764e5f85abf00c7cee4c4e19" title="Loads msg_metadata-&gt;m_call_thread_nickname (if set) or else msg_metadata-&gt;m_call_thread_id,...">set_thread_info_in_msg_metadata()</a>.</li>
</ul>
</li>
<li>The OS thread name can be accessed in various ways; including in Linux:<ul>
<li><code>ps H -C $cmd -o pid\ tid\ cmd\ comm # The comm column will be the thread name; set $proc = process name.</code></li>
<li><code>top -H</code> (thread mode &ndash; or just <code>top</code> and press H key for the same effect).</li>
</ul>
</li>
</ul>
<p >More precisely, there are 3 states for each thread: before <a class="el" href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5" title="Sets or unsets the current thread&#39;s logging-worthy string name; optionally sets the OS thread name (s...">this_thread_set_logged_nickname()</a> is called; after it is called with blank name; and after it's called non-blank name. The semantics are as follows:</p><ul>
<li>Logging-worthy thread string name:<ul>
<li>Initial: As-if <a class="el" href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5" title="Sets or unsets the current thread&#39;s logging-worthy string name; optionally sets the OS thread name (s...">this_thread_set_logged_nickname()</a> was already called with blank name (next bullet).</li>
<li>Blank: The thread string name becomes conceptually null; and the thread ID shall be used instead.</li>
<li>Non-blank: The thread string name becomes equal to <code>thread_nickname</code>.</li>
</ul>
</li>
<li>OS thread name:<ul>
<li>Initial: <code>ps</code>, <code>top</code>, etc. will show the thread name as equal to the process name.</li>
<li>Blank: <code>ps</code>, <code>top</code>, etc. will show the thread name as the thread ID (truncated to N characters, though this is unlikely to be exceeded by real thread IDs).</li>
<li>Non-blank: <code>ps</code>, <code>top</code>, etc. will show the thread name as equal to <code>thread_nickname</code> (truncated to N characters).</li>
<li>Note: Because "Initial" and "Blank" are necessarily not the same, it is recommended to call <a class="el" href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5" title="Sets or unsets the current thread&#39;s logging-worthy string name; optionally sets the OS thread name (s...">this_thread_set_logged_nickname()</a> around thread creation time even if <code>thread_nickname</code> is blank. Then <code>ps</code>, <code>top</code>, etc. output will still be useful and possible to cross-reference with log output, say.</li>
<li>Note: N is documented in <code>man pthread_setname_np</code> as 15 not counting the NUL terminator. Therefore ideally keep the <code>thread_nickname.size()</code> to at most N.</li>
</ul>
</li>
</ul>
<h3>Performance</h3>
<p >Subsequently obtaining the nickname involves a linear string copy; the cost of this is worth considering given that this is potentially done for every single log call site, if the nickname is indeed set. However, most <code>string</code> implementations provide an optimization that uses a <code>union</code> (or equivalent) technique to store short strings in the same place as the data members (pointer, size, capacity) required for long strings; meaning such short <code>string</code>s cost no more to copy than an <em>empty</em> one does. In gcc 5, this is 15 bytes or <code>char</code>s, but implementations vary.</p>
<p >Therefore, it is <em>actively encouraged</em> that you keep the length of <code>thread_nickname</code> low. "Low" depends on the compiler, but keeping it somewhere at or under 15 characters is likely good. If you do so, the effective cost (at a log call site) will be the same as if <code>thread_nickname.empty()</code>, so one could not do better. Note, also, that the OS-name (in Linux) max length happens to also be 15 (see N discussion above), so there is convenient synergy there.</p>
<h3>Thready safety</h3>
<p >This call is safe w/r/t concurrent execution with itself and <a class="el" href="classflow_1_1log_1_1Logger.html#a93541a6407b8705a76c7a161c5289b10" title="ostream manipulator function that, if output via operator&lt;&lt; to an ostream, will cause the current thr...">this_thread_logged_name_os_manip()</a> in other thread(s) for a given <code>*this</code>. It is thread-local in nature.</p>
<h3>Naming rationale</h3>
<p ><a class="el" href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5" title="Sets or unsets the current thread&#39;s logging-worthy string name; optionally sets the OS thread name (s...">this_thread_set_logged_nickname()</a> is an incomplete name, in that it (optionally) also affects the OS thread name. The function was not renamed for compatibility reasons, as the technically incomplete name is in my (ygoldfel) opinion still acceptably descriptive.</p>
<dl class="params"><dt>Parameters</dt><dd>
  <table class="params">
    <tr><td class="paramname">thread_nickname</td><td>New nickname of thread; or "" to request the thread to not be nicknamed (thread ID will be used). In the "" case, no particular thread ID format should ever be assumed; it may be OS-dependent; but it can be informally assumed to be useful for thread identification purposes (probably unique per thread and somewhat readable, etc.). The non-blank value is copied and saved. </td></tr>
    <tr><td class="paramname">logger_ptr</td><td>If non-null, this <code><a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></code> will be used to log an INFO-severity message indicating the thread ID and new nickname (conceptually: [INFO] T...nickname...: Thread ...ID... has new nickname.). If null, nothing is logged. </td></tr>
    <tr><td class="paramname">also_set_os_name</td><td>If and only <code>true</code>, <code>thread_nickname</code> (whether blank or not) also affects the current OS thread name. Otherwise it is not affected.</td></tr>
  </table>
  </dd>
</dl>
<dl class="todo"><dt><b><a class="el" href="todo.html#_todo000048">Todo:</a></b></dt><dd><a class="el" href="classflow_1_1log_1_1Logger.html#a5600c71ccaa294650c7d34b596d90bf5" title="Sets or unsets the current thread&#39;s logging-worthy string name; optionally sets the OS thread name (s...">this_thread_set_logged_nickname()</a> could take multiple <code><a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></code>s, since it is an app-wide function and potentially would want to be reflected in multiple loggers. It could take a pair of iterators or a container (in both cases, of template argument type). Arguably, though, this is overkill; as (1) most code paths deal with only one <code>get_logger()</code>-owning object each; (2) naming of a thread is obvious enough in subsequent logs (hence this message only calls attention to that operation plus notes the thread ID before the nickname assignment, not necessarily the most critical of information). Certainly this zero-to-one-<code><a class="el" href="classflow_1_1log_1_1Logger.html" title="Interface that the user should implement, passing the implementing Logger into logging classes (Flow&#39;...">Logger</a></code> version must continue to be available for syntactic-sugary convenience, even if the to-do is performed. </dd></dl>

<p class="definition">Definition at line <a class="el" href="log_8cpp_source.html#l00036">36</a> of file <a class="el" href="log_8cpp_source.html">log.cpp</a>.</p>

<p class="reference">References <a class="el" href="error_2error_8hpp_source.html#l00269">FLOW_ERROR_SYS_ERROR_LOG_WARNING</a>, <a class="el" href="log_8hpp_source.html#l00197">FLOW_LOG_INFO</a>, <a class="el" href="log_8hpp_source.html#l00405">FLOW_LOG_SET_CONTEXT</a>, <a class="el" href="log_8hpp_source.html#l00152">FLOW_LOG_WARNING</a>, <a class="el" href="util_2util_8hpp_source.html#l00381">flow::util::ostream_op_string()</a>, and <a class="el" href="log_8hpp_source.html#l01552">s_this_thread_nickname_ptr</a>.</p>
<div class="dynheader">
Here is the call graph for this function:</div>
<div class="dyncontent">
<div class="center"><iframe scrolling="no" frameborder="0" src="classflow_1_1log_1_1Logger_a5600c71ccaa294650c7d34b596d90bf5_cgraph.svg" width="679" height="131"><p><b>This browser is not able to show SVG: try Firefox, Chrome, Safari, or Opera instead.</b></p></iframe>
</div>
</div>

</div>
</div>
<h2 class="groupheader">Member Data Documentation</h2>
<a id="a3e00a68f9086f1ef0f4e36b9f23f4d02" name="a3e00a68f9086f1ef0f4e36b9f23f4d02"></a>
<h2 class="memtitle"><span class="permalink"><a href="#a3e00a68f9086f1ef0f4e36b9f23f4d02">&#9670;&nbsp;</a></span>s_this_thread_nickname_ptr</h2>

<div class="memitem">
<div class="memproto">
<table class="mlabels">
  <tr>
  <td class="mlabels-left">
      <table class="memname">
        <tr>
          <td class="memname">boost::thread_specific_ptr&lt; std::string &gt; flow::log::Logger::s_this_thread_nickname_ptr</td>
        </tr>
      </table>
  </td>
  <td class="mlabels-right">
<span class="mlabels"><span class="mlabel">static</span><span class="mlabel">private</span></span>  </td>
  </tr>
</table>
</div><div class="memdoc">

<p>Thread-local storage for each thread's logged name (null pointer, which is default, means no nickname stored). </p>

<p class="definition">Definition at line <a class="el" href="log_8hpp_source.html#l01552">1552</a> of file <a class="el" href="log_8hpp_source.html">log.hpp</a>.</p>

<p class="reference">Referenced by <a class="el" href="log_8cpp_source.html#l00125">set_thread_info()</a>, <a class="el" href="log_8cpp_source.html#l00108">this_thread_logged_name_os_manip()</a>, and <a class="el" href="log_8cpp_source.html#l00036">this_thread_set_logged_nickname()</a>.</p>

</div>
</div>
<hr/>The documentation for this class was generated from the following files:<ul>
<li>log/<a class="el" href="log_8hpp_source.html">log.hpp</a></li>
<li>log/<a class="el" href="log_8cpp_source.html">log.cpp</a></li>
</ul>
</div><!-- contents -->
<!-- start footer part -->
<hr class="footer"/><address class="footer"><small>
Generated on Fri Mar 28 2025 22:55:35 for Flow by&#160;<a href="https://www.doxygen.org/index.html"><img class="footer" src="doxygen.svg" width="104" height="31" alt="doxygen"/></a> 1.9.4
</small></address>
</body>
</html>
